BOJ_2352_반도체 설계
[LIS(Longest Increasing Subsequence) 알고리즘의 응용 문제
|1|2|3|4|5|6|
의 포트를 각각
|4|2|6|3|1|5|
에 꽂아야 한다
단, 연결선이 서로 꼬이지 않아야 하는 것이 이 문제의 핵심이다
즉, 포트는 항상 이전에 꽂힌 선보다 더 높은 숫자의 포트에 꽂힌다
여기까지 생각했으면 LIS를 활용해서 최장 부분 수열을 구하는 문제라는 걸 알 수 있다
그리고 최장 부분 수열의 길이를 구하는 것이므로
이분 탐색만을 활용해서 푸는 것도 가능하다
문제 N이 40000이기 때문에 dp 방식의 LIS로 풀면 시간 초과가 난다
그런데 어째서인지 시간 초과를 확인할 겸 시험 삼아 제출했는데 통과 되었다
의문이지만 이분탐색을 사용해서 푸는 게 맞는 풀이법이다!
DP로 푼 코드
package solve.BJO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.stream.Stream;
public class BJO_2352_반도체_설계 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int[] ports = Stream.of(br.readLine().split(" ")).mapToIntparseInt).toArray(;
// 가장 긴 증가하는 수열 문제
// port에서 가장 긴 증가하는 수열의 길이를 출력하면 된다
int[] dp = new int[n + 1];
Arrays.fill(dp, 1);
for (int i = 0; i < n; i++) {
int port = ports[i];
for (int j = 0; j < i; j++) {
if (ports[j] < port) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
System.out.println(Arrays.stream(dp).max().getAsInt());
}
}
이분탐색으로 푼 코드
package solve.BJO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BJO_2352_반도체_설계_이분탐색 {
public static void main(String[] args) throws IOException {
// 입력
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
int[] ports = new int[n];
for (int i = 0; i < n; i++) {
ports[i] = Integer.parseInt(st.nextToken());
}
int[] lis = new int[n];
int length = 0;
for (int port : ports) {
int pos = binarySearch(lis, port, 0, length);
lis[pos] = port;
if (pos == length) {
length++;
}
}
System.out.println(length);
}
public static int binarySearch(int[] lis, int target, int start, int end) {
while (start < end) {
int mid = start + (end - start) / 2;
if (lis[mid] < target) {
start = mid + 1;
} else {
end = mid;
}
}
return start; // end여도 마찬가지
}
}